package com.bycx.dingxinlc.controller;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.bycx.core.annotation.WechatNeedLogin;
import com.bycx.core.startup.AppConfig;
import com.bycx.core.util.Page;
import com.bycx.core.util.StringUtils;
import com.bycx.dingxinlc.model.TCustPayInfo;
import com.bycx.dingxinlc.service.WechatPayService;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;

/**
 * 微信支付相关
 * 
 * @ClassName: WechatPayController
 * @author Allen
 * @date 2018年4月17日
 */
@Controller
@RequestMapping("/wechat/pay")
public class WechatPayController {
	private Log log = LogFactory.getLog(WechatPayController.class);

	@Autowired
	private WechatPayService wechatPayService;

	/**
	 * 生成预付订单
	 * 
	 * @Title: preOrder
	 * @param @param page
	 * @param @return 参数
	 * @return Page<T> 返回类型
	 * @throws
	 */
	@WechatNeedLogin
	@ResponseBody
	@RequestMapping(value = "/pre", method = RequestMethod.POST)
	public Page<?> preOrder(@RequestBody Page<?> page,
			HttpServletRequest req) {
		log.info("请求生成预付订单，请求参数：" + JSONObject.toJSONString(page.getParams()));

		// 参数检查
		String money = (String) page.getParam("money");

		// 把支付金额保存到session
		HttpSession session = req.getSession();
		session.setAttribute("payFee", money);

		if (StringUtils.isEmpty(money)) {
			page.setSuccess(false);
			page.setMsg("支付金额为空！");
			return page;
		}

		try {
			Map<String, String> map = wechatPayService.preOrder(new BigDecimal(money));
			Map<String, Object> temp = new HashMap<String, Object>();
			for (String k : map.keySet()) {
				temp.put(k, map.get(k));
			}
			page.setMap(temp);
			return page;
		} catch (Exception e) {
			page.setSuccess(false);
			page.setMsg(e.getMessage());
			return page;
		}
	}

	/**
	 * 微信支付回调通知
	 * 
	 * @Title: notify
	 * @param @param req
	 * @param @param res
	 * @param @return 参数
	 * @return String 返回类型
	 * @throws
	 */
	@ResponseBody
	@RequestMapping(value = "/notify", method = RequestMethod.POST)
	public String notify(@RequestBody String xmlStr) throws Exception {
		log.info("=====微信支付回调通知，xml内容：" + xmlStr);

		Map<String, String> result = new HashMap<String, String>();

		// xml转为map
		Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
		log.info("=====微信支付回调通知，转为Map后内容：" + JSONObject.toJSONString(map));

		// 处理回调的状态
		String return_code = map.get("return_code");
		if (!WXPayConstants.SUCCESS.equals(return_code)) {
			log.error("=====微信支付回调状态为：" + return_code);
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "");
			return WXPayUtil.mapToXml(result);
		}

		// 检查签名是否正确
		String key = AppConfig.get("wx_pay_key");
		if (!WXPayUtil.isSignatureValid(map, key)) {
			log.error("=====微信支付回调信息签名错误！");
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "签名失败");
			return WXPayUtil.mapToXml(result);
		}

		// 数据检查
		// 检查appid
		String appId = AppConfig.get("wx_appid");
		String appid = map.get("appid");
		if (!appId.equals(appid)) {
			log.error("=====微信支付回调信息中公众帐号ID错误！回调接口为" + appid + "，我方配置为" + appId);
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "公众账号ID错误");
			return WXPayUtil.mapToXml(result);
		}
		// 检查商户id
		String mchId = AppConfig.get("wx_pay_mch_id");
		String mch_id = map.get("mch_id");
		if (!mchId.equals(mch_id)) {
			log.error("=====微信支付回调信息中商户号错误！回调接口为" + mch_id + "，我方配置为" + mchId);
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "商户号错误");
			return WXPayUtil.mapToXml(result);
		}
		// 检查商户订单号
		String out_trade_no = map.get("out_trade_no");
		if (StringUtils.isEmpty(out_trade_no)) {
			log.error("=====微信支付回调信息中商户订单号为空！");
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "商户订单号为空");
			return WXPayUtil.mapToXml(result);
		}
		// 查询订单
		TCustPayInfo payInfo = wechatPayService.queryPayInfoByOrderNo(out_trade_no);
		if (payInfo == null) {
			log.error("=====微信支付回调信息中的订单[" + out_trade_no + "]在我方数据库不存在");
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "不存在的订单");
			return WXPayUtil.mapToXml(result);
		}
		// 检查openid
		String openid = map.get("openid");
		if (StringUtils.isEmpty(openid)) {
			log.error("=====微信支付回调信息中openid为空");
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "用户标识为空");
			return WXPayUtil.mapToXml(result);
		}
		if (!openid.equals(payInfo.getOpenId())) {
			log.error("=====微信支付回调信息中openid与我方数据库不一致！回调接口为" + openid + "，我方数据库为" + payInfo.getOpenId());
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "用户标识错误");
			return WXPayUtil.mapToXml(result);
		}
		// 检查金额
		String total_fee = map.get("total_fee");
		if (StringUtils.isEmpty(total_fee)) {
			log.error("=====微信支付回调信息中金额为空");
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "订单金额为空");
			return WXPayUtil.mapToXml(result);
		}
		if (new BigDecimal(total_fee).compareTo(payInfo.getOrderAmt().multiply(new BigDecimal(100))) != 0) {
			log.error("=====微信支付回调信息中金额与我方数据库不一致！回调接口为" + total_fee + "分，我方数据库为" + payInfo.getOrderAmt().doubleValue() + "元");
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", "订单金额错误");
			return WXPayUtil.mapToXml(result);
		}

		// 回调处理
		try {
			wechatPayService.updateOrderInfo(map);
			result.put("return_code", WXPayConstants.SUCCESS);
			result.put("return_msg", "OK");
			log.info("=====微信支付回调信息处理成功");
		} catch (Exception e) {
			result.put("return_code", WXPayConstants.FAIL);
			result.put("return_msg", e.getMessage());
			log.error("=====微信支付回调信息处理失败，失败信息：" + e.getMessage(), e);
		}

		return WXPayUtil.mapToXml(result);
	}

}
